package cc.rengu.igas.bomp.core.service.base;

import cc.rengu.igas.bomp.common.constant.BompAppParamConstant;
import cc.rengu.igas.bomp.common.constant.BompTreeNodeConstant;
import cc.rengu.igas.bomp.common.dao.*;
import cc.rengu.igas.bomp.common.dao.impl.*;
import cc.rengu.igas.bomp.common.entity.*;
import cc.rengu.igas.bomp.common.enums.RespCodeEnum;
import cc.rengu.igas.bomp.core.model.UserSessionInfo;
import cc.rengu.igas.bomp.core.realize.BspsPublicService;
import cc.rengu.igas.bomp.core.realize.NormalMchntInfoService;
import cc.rengu.igas.bomp.core.realize.UserPermissionCheckService;
import cc.rengu.igas.bomp.core.realize.impl.BspsPublicServiceImpl;
import cc.rengu.igas.bomp.core.realize.impl.NormalMchntInfoServiceImpl;
import cc.rengu.igas.bomp.core.realize.impl.UserPermissionCheckServiceImpl;
import cc.rengu.igas.share.common.enums.RoleTypeEnum;
import cc.rengu.igas.share.core.model.MchntBindInfo;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.RiskMonitorServiceImpl;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.base.BizBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.RiskMonitorInfo;
import cc.rengu.oltp.service.realize.RiskMonitorService;
import cc.rengu.oltp.utility.annotation.BIZ_AFTER;
import cc.rengu.oltp.utility.annotation.BIZ_PROCESS;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by 王成 on 2020/3/5
 */
public abstract class ManageService extends BizBaseService {
    @Override
    protected Object beforeBizProcess() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        /* Step1：业务调用前公共处理 */
        String txnNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM);
        String msgSrcId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SRC_SYS_ID);
        String channelId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.CHANNEL_ID);
        String mchntNo = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.MCHNT_NO);
        String chainMchntNo = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.CHAIN_MCHNT_NO);
        String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
        String userId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.USER_ID);
        String sessionId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SESSION);
        String managerId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.MANAGER_ID);
        if (StringUtil.isEmptyOrNull(instId) || StringUtil.isEmptyOrNull(txnNum) || StringUtil.isEmptyOrNull(channelId)) {
            rglog.error("参数必填性校验失败!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        /* Step2：根据源系统标识及调用渠道确认用户角色 */
        String userRole = null;
        ManagerInfo managerInfo = null;
        if (!StringUtil.isEmptyOrNull(userId)) {
            if (msgSrcId.equals(ChannelEnum.COPS.getChannelType())) {
                /* Step2.1：判断用户是否为拓展经理 */
                String agentMchntNo = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.AGENT_MCHNT_NO);
                ManagerInfoMapper managerInfoMapper = new ManagerInfoMapperImpl();
                managerInfo = managerInfoMapper.selectManagerInfoByPrimaryKey(instId, (null == agentMchntNo) ? instId : agentMchntNo, userId);
                userRole = (null != managerInfo) ? managerInfo.getRoleType() : null;
                xmlTreeUtil.setXmlTreeObjectValue("managerInfo", managerInfo);
            } else if (msgSrcId.equals(ChannelEnum.BSPS.getChannelType())) {
                /* Step2.2：获取用户信息 */
                UserPermissionCheckService userService = new UserPermissionCheckServiceImpl();
                UserSessionInfo userSessionInfo = userService.checkUserLoginSessionStatus(instId, sessionId, userId);
                /* Step2.3：签名校验 */
                String verifySignFlag = xmlTreeUtil.getXmlTreeStringValue(BompTreeNodeConstant.VERIFY_SIGN_FLAG);
                if (AppParamConstant.YES.equals(txnInfo.getSrcTxnAuthCfg().getSignFlag()) && AppParamConstant.NO.equals(verifySignFlag)) {
                    if (null == userSessionInfo) {
                        rglog.error("获取用户会话信息失败，用户未登陆或者会话已过期!");
                        throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
                    } else {
                        rglog.error("签名验证失败，交易码:<{}>", txnNum);
                        throw new BizException(RespCodeEnum.VERIFY_SIGN_ERROR.getRespCode(), RespCodeEnum.VERIFY_SIGN_ERROR.getRespDesc());
                    }
                }
                /* Step2.4：获取用户角色 */
                if ("WECHAT".equals(channelId) || "PCWEB".equals(channelId) || "MOBILE".equals(channelId) || "APP".equals(channelId)) {
                    if (null != userSessionInfo) {
                        /* Step2.4.1：判断用户是否为拓展经理 */
                        ManagerInfoMapper managerInfoMapper = new ManagerInfoMapperImpl();
                        if ("APP".equals(channelId)){
                            managerInfo = managerInfoMapper.selectManagerInfoById(instId,userId);
                        }else {
                            managerInfo = managerInfoMapper.selectManagerInfoByOpenId(instId, userId);
                        }
                        if (null != managerInfo) {
                            userRole = managerInfo.getRoleType();
                            xmlTreeUtil.setXmlTreeObjectValue("managerInfo", managerInfo);
                        }
                    } else {
                        /* Step2.4.2：获取商户绑定信息 */
                        BspsPublicService bspsPublicService = new BspsPublicServiceImpl();
                        List<MchntBindInfo> mchntBindInfoList = bspsPublicService.getMchntBindInfo(instId, userId, mchntNo);
                        if (null == mchntBindInfoList && !StringUtil.isEmptyOrNull(chainMchntNo)) {
                            mchntBindInfoList = bspsPublicService.getMchntBindInfo(instId, userId, chainMchntNo);
                        } else if (!StringUtil.isEmptyOrNull(mchntNo)) {
                            MchntBaseInfoMapper mchntBaseInfoMapper = new MchntBaseInfoMapperImpl();
                            MchntBaseInfo mchntBaseInfo = mchntBaseInfoMapper.selectMchntBaseInfoByPrimaryKey(instId, mchntNo);
                            mchntBindInfoList = bspsPublicService.getMchntBindInfo(instId, userId, mchntBaseInfo.getChainMchntNo());
                        } else {
                            mchntBindInfoList = bspsPublicService.getMchntBindInfo(instId, userId, null);
                        }
                        if (null != mchntBindInfoList && !mchntBindInfoList.isEmpty()) {
                            userRole = mchntBindInfoList.get(0).getBindUserRole();
                        }
                    }
                    /* Step2.4.3：根据角色查询用户交易权限 */
                    if (StringUtil.isEmptyOrNull(userRole)) {
                        //可能为平台商/集团商/代理商
                        BspsPublicService bspsPublicService = new BspsPublicServiceImpl();
                        List<MchntBindInfo> mchntBindInfoList = bspsPublicService.getMchntBindInfo(instId, userId, null);
                        if (!CollectionUtils.isEmpty(mchntBindInfoList)) {
                            List<MchntBindInfo> mchntList = mchntBindInfoList.stream().filter(item -> RoleTypeEnum.GROUP_MCHNT.getRoleType().equals(item.getBindUserRole())
                                    || RoleTypeEnum.PLAT_MCHNT.getRoleType().equals(item.getBindUserRole())
                                    || RoleTypeEnum.AGENT_MCHNT.getRoleType().equals(item.getBindUserRole())).collect(Collectors.toList());
                            if (CollectionUtils.isEmpty(mchntList)) {
                                rglog.info("该用户无绑定商户，userId:<{}>,txnNum:<{}>", userId, txnNum);
                                throw new BizException(RespCodeEnum.USER_NO_AUTHORITY.getRespCode(), RespCodeEnum.USER_NO_AUTHORITY.getRespDesc());
                            }
                        }
                    }
                    BompUserRoleInfoMapper bompUserRoleInfoMapper = new BompUserRoleInfoMapperImpl();
                    UserRoleInfo userRoleInfo = bompUserRoleInfoMapper.selectBompUserRoleInfoByRoleTypeAndTxnNum(instId, userRole, txnNum, channelId);
                    if (null == userRoleInfo) {
                        rglog.info("该用户无该交易权限，userId:<{}>,mchntNo:<{}>,txnNum:<{}>", userId, mchntNo, txnNum);
                        throw new BizException(RespCodeEnum.USER_NO_AUTHORITY.getRespCode(), RespCodeEnum.USER_NO_AUTHORITY.getRespDesc());
                    }
                } else {
                    rglog.error("渠道信息错误", channelId);
                    throw new BizException(RespCodeEnum.ILLEGAL_OPERATION.getRespCode(), RespCodeEnum.ILLEGAL_OPERATION.getRespDesc());
                }
            } else if (msgSrcId.equals(ChannelEnum.BOMP.getChannelType())) {
                if ("UPMP".equals(channelId)) {
                    UserService userService = new UserServiceImpl();
                    UserInfo userInfo = userService.getUserInfo(instId, userId, sessionId);
                    if (null == userInfo) {
                        rglog.error("内管用户信息查询失败", userId);
                        throw new BizException(RespCodeEnum.QUERY_AUTH_USER_IS_NULL.getRespCode(), RespCodeEnum.QUERY_AUTH_USER_IS_NULL.getRespDesc());
                    }
                    userRole = AppParamConstant.DEFAULT_INSTID.equals(instId) ? "admin" : "bankManager";
                } else if ("MCMP".equals(channelId)) {
                    //基于ECP版本內管來使用原來ECP的用戶表
                    AuthUserMapper authUserMapper = new AuthUserMapperImpl();
                    AuthUser authUser = authUserMapper.selectAuthUserById(userId);
                    if (null == authUser) {
                        rglog.error("BOMP用户信息查询失败", userId);
                        throw new BizException(RespCodeEnum.QUERY_AUTH_USER_IS_NULL.getRespCode(), RespCodeEnum.QUERY_AUTH_USER_IS_NULL.getRespDesc());
                    }
                    userRole = AppParamConstant.DEFAULT_INSTID.equals(authUser.getInstId()) ? "admin" : "bankManager";
                    /* 根据用户信息查询拓展经理（审核员）信息 */
                    if (!StringUtil.isEmptyOrNull(managerId) || !StringUtil.isEmptyOrNull(authUser.getEmpNo())) {
                        String queryManageId = !StringUtil.isEmptyOrNull(managerId) ? managerId : authUser.getEmpNo();
                        ManagerInfoMapper managerInfoMapper = new ManagerInfoMapperImpl();
                        managerInfo = managerInfoMapper.selectManagerInfoByPrimaryKey(instId, authUser.getOrgCode(), queryManageId);
                    }
                } else if ("WECHAT".equals(channelId) || "PCWEB".equals(channelId) || "MOBILE".equals(channelId) || "BSPS".equals(channelId) || "APP".equals(channelId)) {
                    BompUserInfoMapper bompUserInfoMapper = new BompUserInfoMapperImpl();
                    BspsUserInfo bspsUserInfo = bompUserInfoMapper.selectBompBspsUserInfoByUserId(instId, userId);
                    if (null == bspsUserInfo) {
                        ManagerInfoMapper managerInfoMapper = new ManagerInfoMapperImpl();
                        if ("APP".equals(channelId)){
                            managerInfo = managerInfoMapper.selectManagerInfoById(instId,userId);
                        }else {
                            managerInfo = managerInfoMapper.selectManagerInfoByOpenId(instId, userId);
                        }
                        if (null != managerInfo) {
                            userRole = managerInfo.getRoleType();
                            xmlTreeUtil.setXmlTreeObjectValue("managerInfo", managerInfo);
                        }
                    } else {
                        /* 获取商户绑定信息 */
                        BspsPublicService bspsPublicService = new BspsPublicServiceImpl();
                        List<MchntBindInfo> mchntBindInfoList = bspsPublicService.getMchntBindInfo(instId, userId, mchntNo);
                        if (null == mchntBindInfoList){
                            if (!StringUtil.isEmptyOrNull(chainMchntNo)) {
                                mchntBindInfoList = bspsPublicService.getMchntBindInfo(instId, userId, chainMchntNo);
                            } else if (!StringUtil.isEmptyOrNull(mchntNo)) {
                                MchntBaseInfoMapper mchntBaseInfoMapper = new MchntBaseInfoMapperImpl();
                                MchntBaseInfo mchntBaseInfo = mchntBaseInfoMapper.selectMchntBaseInfoByPrimaryKey(instId, mchntNo);
                                mchntBindInfoList = bspsPublicService.getMchntBindInfo(instId, userId, mchntBaseInfo.getChainMchntNo());
                            } else {
                                mchntBindInfoList = bspsPublicService.getMchntBindInfo(instId, userId, null);
                            }
                        }
                        if (null != mchntBindInfoList && !mchntBindInfoList.isEmpty()) {
                            userRole = mchntBindInfoList.get(0).getBindUserRole();
                        }
                        /* 根据角色查询用户交易权限 */
                        if (StringUtil.isEmptyOrNull(userRole)) {
                            //可能为平台商/集团商/代理商
                            mchntBindInfoList = bspsPublicService.getMchntBindInfo(instId, userId, null);
                            if (!CollectionUtils.isEmpty(mchntBindInfoList)) {
                                List<MchntBindInfo> mchntList = mchntBindInfoList.stream().filter(item -> RoleTypeEnum.GROUP_MCHNT.getRoleType().equals(item.getBindUserRole())
                                        || RoleTypeEnum.PLAT_MCHNT.getRoleType().equals(item.getBindUserRole())
                                        || RoleTypeEnum.AGENT_MCHNT.getRoleType().equals(item.getBindUserRole())).collect(Collectors.toList());
                                if (CollectionUtils.isEmpty(mchntList)) {
                                    rglog.info("该用户无绑定商户，userId:<{}>,txnNum:<{}>", userId, txnNum);
                                    throw new BizException(RespCodeEnum.USER_NO_AUTHORITY.getRespCode(), RespCodeEnum.USER_NO_AUTHORITY.getRespDesc());
                                }
                            }
                        }
                        xmlTreeUtil.setXmlTreeObjectValue("mchntBindInfo", mchntBindInfoList);
                        if ("WECHAT".equals(channelId) || "PCWEB".equals(channelId) || "MOBILE".equals(channelId)) {
                            BompUserRoleInfoMapper bompUserRoleInfoMapper = new BompUserRoleInfoMapperImpl();
                            UserRoleInfo userRoleInfo = bompUserRoleInfoMapper.selectBompUserRoleInfoByRoleTypeAndTxnNum(instId, userRole, txnNum, channelId);
                            if (null == userRoleInfo) {
                                rglog.info("该用户无该交易权限，userId:<{}>,mchntNo:<{}>,txnNum:<{}>", userId, mchntNo, txnNum);
                                throw new BizException(RespCodeEnum.USER_NO_AUTHORITY.getRespCode(), RespCodeEnum.USER_NO_AUTHORITY.getRespDesc());
                            }
                        }
                    }
                }
            }
        }

        /* 把扩展经理信息放到树里,方便后面使用 */
        xmlTreeUtil.setXmlTreeObjectValue("managerInfo", managerInfo);

        if (!StringUtil.isEmptyOrNull(userRole)) {
            xmlTreeUtil.setXmlTreeStringValue("userRole", userRole);
        }

        /* Step3：如果商户号不为空检查商户状态，并将商户基础信息放入XML树 */
        if (!StringUtils.isEmpty(mchntNo) && !StringUtils.isEmpty(userRole) && BompAppParamConstant.MCHNT_ROLES.contains(userRole)) {
            NormalMchntInfoService mchntCheckService = new NormalMchntInfoServiceImpl();
            MchntBaseInfo mchntBaseInfo = mchntCheckService.checkMchntStatus(instId, mchntNo);
            xmlTreeUtil.setXmlTreeObjectValue(BompTreeNodeConstant.MCHNT_BASE_INFO, mchntBaseInfo);
        }

        /* Step4：业务调用前客户化处理 */
        return bizBeforeCust();
    }

    @Override
    protected BizResponse callBizService(Object request) throws Exception {
        /* Step1：公共业务处理 */

        /* Step2：查找BIZ_PROCESS的注解 */
        invokeBizAnnoMethod(BIZ_PROCESS.class);

        /* Step3：业务逻辑处理 */
        return bizProcessCust(request);
    }

    @Override
    protected void afterBizProcess(BizResponse response) throws Exception {
        /* Step1：业务调用后公共处理*/

        /* Step2：查找BIZ_AFTER的注解 */
        invokeBizAnnoMethod(BIZ_AFTER.class);

        /* Step3：业务调用后客户化处理 */
        bizAfterCust(response);
    }

    @Override
    protected RiskMonitorInfo getRiskMonitorInfo() {
        RiskMonitorInfo riskMonitorInfo = new RiskMonitorInfo();
        RiskMonitorService riskMonitorService = new RiskMonitorServiceImpl();
        riskMonitorInfo.setTransMonitor(riskMonitorService);
        return riskMonitorInfo;
    }

    /**
     * 业务处理前客户化处理
     *
     * @return 业务处理实体类
     */
    protected abstract Object bizBeforeCust() throws Exception;

    /**
     * 业务逻辑处理客户化处理
     *
     * @param request 业务处理前的返回实体类
     * @return 业务处理结果
     */
    protected abstract BizResponse bizProcessCust(Object request) throws Exception;

    /**
     * 业务处理后逻辑处理
     *
     * @param response 业务调用响应信息
     */
    protected abstract void bizAfterCust(Object response) throws Exception;
}
